package top.withu.gaof.freehope.aspect;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import top.withu.gaof.freehope.annotate.LogProps;
import top.withu.gaof.freehope.annotate.PassCheck;
import top.withu.gaof.freehope.dao.UserApiDao;
import top.withu.gaof.freehope.dao.UserDao;
import top.withu.gaof.freehope.model.User;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @author Gaofan
 * @date 2019年4月24日 下午2:35:25
 * @describe 拦截进行权限校验
 */
public class AuthenticationInterceptor implements HandlerInterceptor {

	@Autowired
	private UserDao userDao;
	@Autowired
	private UserApiDao userApiDao;


	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {


		String token = request.getHeader("Authorization");
		// 如果不是映射到方法直接通过
		if (!(handler instanceof HandlerMethod)) {
			return true;
		}
		HandlerMethod handlerMethod = (HandlerMethod) handler;
		Method method = handlerMethod.getMethod();
		// 检查是否有passtoken注释，有则跳过认证
		if (method.isAnnotationPresent(PassCheck.class)) {
			PassCheck passToken = method.getAnnotation(PassCheck.class);
			if (passToken.required()) {
				return true;
			}
		}
		// 非注解方法，进行权限校验
		if (token == null) {
			throw new RuntimeException("无token，请重新登录");
		}
		// 获取 token 中的 user id
		String userName;
		try {
			userName = JWT.decode(token).getAudience().get(0);
		} catch (JWTDecodeException j) {
			throw new RuntimeException("您的token无效，请联系管理员哦！");
		}
		User user = userDao.findTop1ByUserNameAndIsExpire(userName, Boolean.FALSE,
				new Sort(Sort.Direction.DESC, "createTime"));
		if (user == null) {
			throw new RuntimeException("用户不存在，请重新登录");
		}
		// 验证 token
		JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPwd())).build();
		try {
			jwtVerifier.verify(token);
		} catch (JWTVerificationException e) {
			throw new RuntimeException("您的token校验失败，可能是失效了！");
		}
		// 获取注解中apiId，判断用户是否具有该接口权限
		if (!method.isAnnotationPresent(LogProps.class)) {
			throw new RuntimeException("该接口apiId为空，试图跳过校验，请开发人员注意！");
		}
		LogProps logProps = method.getAnnotation(LogProps.class);
		int isAuthorize = userApiDao.countByUserIdAndApiIdAndIsExpire(user.getId(), logProps.apiId(), Boolean.FALSE);
		if (isAuthorize == 0) {
			throw new RuntimeException("您的账号不具有该api访问权限，请您确认！");
		}
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub

	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub

	}

}
